# Copyright (c) 2018 Red Hat, Inc. All rights reserved. This copyrighted
# material is made available to anyone wishing to use, modify, copy, or
# redistribute it subject to the terms and conditions of the GNU General Public
# License v.2 or later.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
# details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc., 51
# Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
"""The "component" command."""
import re

from kpet import cmd_misc
from kpet import data
from kpet import misc


def build(cmds_parser, common_parser):
    """Build the argument parser for the component command."""
    _, action_subparser = cmd_misc.build(
        cmds_parser,
        common_parser,
        "component",
        help='Build component',
    )
    list_parser = action_subparser.add_parser(
        "list",
        help='List recognized build components.',
        parents=[common_parser],
    )
    list_parser.add_argument(
        '-t',
        '--trees',
        metavar='REGEX',
        help='A regular expression matching the names of kernel trees, which '
             'listed components should match. '
             'Run "kpet tree list" to see recognized trees. '
    )
    list_parser.add_argument(
        '-a',
        '--arches',
        metavar='REGEX',
        help='A regular expression matching the names of architectures, which '
             'listed components should match. '
             'Run "kpet arch list" to see supported architectures. '
    )
    list_parser.add_argument(
        '-c',
        '--components',
        metavar='REGEX',
        help='A regular expression matching other components included '
             'into the kernel build, which listed components should match. '
             'Run "kpet component list" to see recognized components.'
    )
    list_parser.add_argument('regex', nargs='?', default=None,
                             help='Regular expression fully matching '
                                  'names of components to output.')


def main(args):
    """Execute the `component` command."""
    if not data.Base.is_dir_valid(args.db):
        misc.raise_invalid_database(args.db)
    database = data.Base(args.db)
    if args.action == 'list':
        trees_target_sets = [None]
        arches_target_sets = [None]
        components_target_set = None
        if args.trees is not None:
            trees_target_sets = [{x} for x in database.trees
                                 if re.fullmatch(args.trees, x)]
            if database.trees and not trees_target_sets:
                raise Exception("No trees matched specified regular "
                                f"expression: {args.trees}")
        if args.arches is not None:
            arches_target_sets = [{x} for x in database.arches
                                  if re.fullmatch(args.arches, x)]
            if database.arches and not arches_target_sets:
                raise Exception("No architectures matched specified regular "
                                f"expression: {args.arches}")
        if args.components is not None:
            components_target_set = set(x for x in database.components
                                        if re.fullmatch(args.components, x))

        regex = re.compile(".*" if args.regex is None else args.regex)
        max_name_length = max((len(k) for k in database.components), default=0)
        for name, component in sorted(database.components.items(),
                                      key=lambda i: i[0]):
            if regex.fullmatch(name) and any(
                component.supported.matches(data.Target(
                    arches=arches_target_set,
                    trees=trees_target_set,
                    components=components_target_set
                ))
                for trees_target_set in trees_target_sets
                for arches_target_set in arches_target_sets
            ):
                print(f"{name: <{max_name_length}} {component.description}")
    else:
        misc.raise_action_not_found(args.action, args.command)
